package server;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.client.AMQP.BasicProperties;

import entities.ConnectParameters;
import entities.ProductionOrder;
import entities.QCReport;
import entities.RequestParameters;
import net.miginfocom.swing.MigLayout;

import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
import javax.swing.JLabel;
  
/**
 * @author Idan
 * Server instance.
 * The server receives a Byte[] which is then converted into ArrayList, where
 * index 0 holds the command requested.
 * Nested if else statements deduce the requested command, which is then
 * executed and sent it's parameters.
 */
public class Server
{

  private static Connection connection;
  private static Channel channel;
  private static final String RPC_QUEUE_NAME = "rpc_queue"; 
  public static mySQL sqlServer;
 
  /**
   * Handles the requests from the clients.
   * message's 0 index holds the command string, the rest are the parameters.
   */
  private static ArrayList<Object> handleRequest (ArrayList<Object> message) throws SQLException
  {
	
	  String command = message.get(0).toString();
	 // Do something
	
      if ( command.equalsIgnoreCase("initializeAllFieldsMPM"))
    	  return sqlServer.initializeAllFieldsMPM();    
      else
   	 
   	  if ( command.equalsIgnoreCase("createNewSchedule"))
   	  return sqlServer.createNewSchedule((String)message.get(1), (ArrayList<String>)message.get(2),(ArrayList<String>)message.get(3),(ArrayList<String>)message.get(4),(ArrayList<String>)message.get(5));
      else
   	  if (command.equalsIgnoreCase("getSchedule"))
   		  return sqlServer.getSchedule((String)message.get(1));
   	  else    	  
      if ( command.equalsIgnoreCase("createNewOrder"))
    	  return sqlServer.createNewOrder((ProductionOrder)message.get(1));
      else
      if (command.equalsIgnoreCase("deleteOrder"))
    	  return sqlServer.deleteOrder((ProductionOrder)message.get(1));
      else
      if( command.equalsIgnoreCase("initializeAllFieldsEngraving"))
    	  return sqlServer.initializeAllFieldsEngraving();
     else
      if (command.equalsIgnoreCase("getOrderIdData"))
    	  return sqlServer.getOrderIdData(message.get(1).toString());
     else
      if (command.equalsIgnoreCase("newEngraveReport"))
    	  return sqlServer.newEngraveReport((ProductionOrder)message.get(1));
     else
      if (command.equalsIgnoreCase("newSeparationReport"))
    	  return sqlServer.newSeparationReport((ProductionOrder)message.get(1));
      else
      if (command.equalsIgnoreCase("deleteEngraveReport"))
    	  return sqlServer.deleteEngraveReport((ProductionOrder)message.get(1));
      else
      if (command.equalsIgnoreCase("initializePolishPane"))
          return sqlServer.initializePolishPane();      
      else
      if(command.equalsIgnoreCase("initializeStartPolish"))
    	  return sqlServer.initializeStartPolish(message);
      else
      if(command.equalsIgnoreCase("initializeComboJarIDBox"))
    	  return sqlServer.initializeComboJarIDBox();
      else
      if(command.equalsIgnoreCase("initializeOrderIDComboBox"))
    	  return sqlServer.initializeOrderIDComboBox();
      else
      if(command.equalsIgnoreCase("addNewPolish"))
    	  return sqlServer.addNewPolish(message);
      else
      if(command.equalsIgnoreCase("initializeAllFieldsVPOP"))
    	  return sqlServer.initializeAllFieldsVPOfOperations( (Timestamp)message.get(1), (Timestamp)message.get(2), (Timestamp)message.get(3) );
      else
      if (command.equalsIgnoreCase("getValuesForDashboard"))
    	  return sqlServer.valuesForDashboard((Timestamp)message.get(1), (Timestamp)message.get(2), (Timestamp)message.get(3));
   	  else
   	  if(command.equalsIgnoreCase("removeFromPolish"))
   		  return sqlServer.removeFromPolish(message);
   	  else
      if(command.equalsIgnoreCase("searchOrderID"))
    	  return sqlServer.searchOrderID(message);
      else 
      if (command.equalsIgnoreCase("getJarContents"))
    	  return sqlServer.getJarContents(message);
      else
      if (command.equalsIgnoreCase("setStatusIDByOrderID"))
   		  return sqlServer.setStatusIDByOrderID(message);
      else
      if(command.equalsIgnoreCase("getPolishID"))
   		  return sqlServer.getPolishID(message);
      else
      if (command.equalsIgnoreCase("setEndDateInPolishByPolishID"))
   		  return sqlServer.setEndDateInPolishByPolishID(message);
      else
      if (command.equalsIgnoreCase("replacePellets"))
    	  return sqlServer.replacePellets(message);
      else
      if(command.equalsIgnoreCase("updateExtraDays"))
   		  return sqlServer.updateExtraDays(message);
      else 
      if(command.equalsIgnoreCase("initializePackageMailPanelVariables"))
   		  return sqlServer.initializePackageMailPanelVariables(message);
   	  else
   	  if(command.equalsIgnoreCase("initializeAllFieldsQualityControl"))
   		  return sqlServer.initializeAllFieldsQualityControl();
   	  else
   	  if(command.equalsIgnoreCase("getPelletsCyclesNumber"))
   		  return sqlServer.getPelletsCyclesNumber(message);
   	  else
   	  if(command.equalsIgnoreCase("updatePelletsCycles"))
   		  return sqlServer.updatePelletsCycles(message);
   	  else
  	  if (command.equalsIgnoreCase("addNewQCReport"))
   		  return sqlServer.addNewQCReport((QCReport)message.get(1));   
   	  else
   	  if(command.equalsIgnoreCase("updateCommentsIntoPolishRow"))
   		  return sqlServer.updateCommentsIntoPolishRow(message);
   	  else
   	  if(command.equalsIgnoreCase("updateGuiCommentsFromPolish"))
   		  return sqlServer.updateGuiCommentsFromPolish(message);
   	  else
      if(command.equalsIgnoreCase("addNewPackageReport"))
   		  return sqlServer.addNewPackageReport(message);
   	  else
   	  if(command.equalsIgnoreCase("checkExistingRowPackagingReport"))
   		  return sqlServer.checkExistingRowPackagingReport(message);
   	  else
   	  if(command.equalsIgnoreCase("updateNewPackageReport"))
   		  return sqlServer.updateNewPackageReport(message);
   	  else
   	  if(command.equalsIgnoreCase("getPackageEmployeesNames"))
   		  return sqlServer.getPackageEmployeesNames(message);
   	  else
   	  if(command.equalsIgnoreCase("getOrderIDQuantity"))
   		  return sqlServer.getOrderIDQuantity(message);
   	  else
   	  if (command.equalsIgnoreCase("getFailQuantityReport"))
   		 return sqlServer.getFailQuantityReport((RequestParameters)message.get(1));
   	  else
	  if (command.equalsIgnoreCase("getFailPercentagesReport"))
 		  return sqlServer.getFailPercentagesReport((RequestParameters)message.get(1));
	  else
	  if (command.equalsIgnoreCase("getFailQuantitiesByEngraveMonth"))
 		  return sqlServer.getFailQuantitiesByEngraveMonth((RequestParameters)message.get(1));
   	  else
   	  if (command.equalsIgnoreCase("getFailQuantitiesByQCMonth"))
   		  return sqlServer.getFailQuantitiesByQCMonth((RequestParameters)message.get(1));
   	  else
   	  if (command.equalsIgnoreCase("getFailQuantitiesByReason"))
   		  return sqlServer.getFailQuantitiesByReason((RequestParameters)message.get(1));
   	  else
      if (command.equalsIgnoreCase("getFailQuantitiesByLine"))
    	  return sqlServer.getFailQuantitiesByLine((RequestParameters)message.get(1));
      else
      if (command.equalsIgnoreCase("getEngraveQuantityByEmployeeReport"))
    	  return sqlServer.getEngraveQuantityByEmployeeReport((RequestParameters)message.get(1));
      else
      if (command.equalsIgnoreCase("getFailQuantityByEmployeeReport"))
    	  return sqlServer.VPOfOperationsFailQuantitiesByEmployeeReport((RequestParameters)message.get(1));
      else
      if (command.equalsIgnoreCase("getFailPercentagesByTimeEngraveReport"))
    	  return sqlServer.getFailPercentagesByTimeEngraveReport((RequestParameters)message.get(1));
      else
      if (command.equalsIgnoreCase("getFailPercentagesByTimeQCReport"))
    	  return sqlServer.getFailPercentagesByTimeQCReport((RequestParameters)message.get(1));
      else
      if (command.equalsIgnoreCase("getQuantitiesByProductReport"))
    	  return sqlServer.getQuantitiesByProductReport((RequestParameters)message.get(1));
      else
      if (command.equalsIgnoreCase("getRawMaterialsReport"))
       	  return sqlServer.getRawMaterialsReport((RequestParameters)message.get(1));
      else
   	  if (command.equalsIgnoreCase("discardPackage"))
   		  return sqlServer.discardPackage(message);
   	  else
      if(command.equalsIgnoreCase("createNewOrderhashmasha"))
    	  return sqlServer.createNewOrderhashmasha(message);
      else
      if(command.equalsIgnoreCase("createNewPackageHashmasha"))
    	  return sqlServer.createNewPackageHashmasha(message);
      else
      if(command.equalsIgnoreCase("getListOfProducts"))
    	  return sqlServer.getListOfProducts();
      else
      if(command.equalsIgnoreCase("finishPackaging"))
    	  return sqlServer.finishPackaging(message);
      else
      if(command.equalsIgnoreCase("initializeVPOfOperationsTabbedPolishReport"))
    	  return sqlServer.initializeVPOfOperationsTabbedPolishReport(message);
      else
      if(command.equalsIgnoreCase("initializeVPOfOperationsTabbedEngraveReport"))
    	  return sqlServer.initializeVPOfOperationsTabbedEngraveReport(message);
      else
      if(command.equalsIgnoreCase("initializeVPOfOperationsTabbedQCReport"))
    	  return sqlServer.initializeVPOfOperationsTabbedQCReport(message);
      else
      if(command.equalsIgnoreCase("initializeVPOfOperationsTabbedPackagingReport"))
    	  return sqlServer.initializeVPOfOperationsTabbedPackagingReport(message);
      else
      if(command.equalsIgnoreCase("getQuantitiesBySubFamilyReport"))
       	  return sqlServer.getQuantitiesBySubFamilyReport((RequestParameters)message.get(1));
      else
      if(command.equalsIgnoreCase("initializeVPOfOperationsTabbedHashmashaReport"))
    	  return sqlServer.initializeVPOfOperationsTabbedHashmashaReport(message);
      else
      if(command.equalsIgnoreCase("initializeVPOfOperationsTabbedDiscardReport"))
    	  return sqlServer.initializeVPOfOperationsTabbedDiscardReport(message);
      else
      if(command.equalsIgnoreCase("largeTableToExcel"))
    	  return sqlServer.largeTableToExcel(message.get(1).toString(),message.get(2).toString(),message.get(3).toString());
      else
    	  return (ArrayList<Object>) (message.set(0, "Invalid"));
	
  }
     
  /**
   * Initialize conncection to mySQL database using the received parameters.
   * @param host
   * @param port
   * @param databaseName
   * @param username
   * @param password
   */
  public void runServer(String host, String port, String databaseName, String username, String password)
  {
    connection = null;
    channel = null;
    
    sqlServer = new mySQL("mysql://" + host + ":" + port + "/" + databaseName ,username,password);

    try
    {
      ConnectionFactory factory = new ConnectionFactory();
      ConnectParameters parameters = new ConnectParameters();
      if (parameters.readParameters())
      {
      	
      	
      	factory.setHost(parameters.getHost());
      	factory.setPort(Integer.parseInt(parameters.getPort()));
      	factory.setVirtualHost(parameters.getVirtualHost());
      	factory.setUsername(parameters.getUsername());
        factory.setPassword(parameters.getPassword());

          
      }
      else
      {
      	System.out.println("could not load config.properties");
      	
      	JOptionPane.showMessageDialog(new JPanel(),
  			    "לא ניתן להפעיל את השרת.","שגיאה",JOptionPane.ERROR_MESSAGE);
      	
      	System.exit(0);
      	return;
      }
      
      connection = factory.newConnection();
      channel = connection.createChannel();
      
      channel.queueDeclare(RPC_QUEUE_NAME, false, false, false, null);
  
      channel.basicQos(1);
  
      QueueingConsumer consumer = new QueueingConsumer(channel);
      channel.basicConsume(RPC_QUEUE_NAME, false, consumer);
  
  
      while (true)
      {
        ArrayList<Object> response = new ArrayList<Object>();
        
        QueueingConsumer.Delivery delivery = consumer.nextDelivery();
        
        BasicProperties props = delivery.getProperties();
        BasicProperties replyProps = new BasicProperties
                                         .Builder()
                                         .correlationId(props.getCorrelationId())
                                         .build();
        
        try
        {
        	ArrayList<Object> receivedMessage = utilities.Services.convertByteArrayToArrayList(delivery.getBody());
                response = handleRequest(receivedMessage);
  
      
        }
        catch (Exception e)
        {
          
        }
        finally
        {  
        	
        	
        	
        	//Send reply back to the client
        
          channel.basicPublish( "", props.getReplyTo(), replyProps, utilities.Services.convertArrayListToByteArray(response));
          channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        }
      }
    }
    catch  (Exception e) 
    {
    	System.exit(0);
    //e.printStackTrace();
    }
    finally {
      if (connection != null)
      {
        try
        {
          connection.close();
          
        }
        catch (Exception ignore) {}
      }
    }      		      
  }

  /**
   * Closes the server instance
   * @return
   */
public static boolean closeSrver()
{
	try
	{
		channel.close();
		connection.close();
		
		return true;
	} 
	catch (IOException e) 
	{
		
		//e.printStackTrace();
		return false;
	}
	
}
}
